﻿#region

using System.Collections.Generic;
using System.Text;
using OMS.Ice.T4Generator.Properties;
using OMS.Ice.T4Generator.Syntax;

#endregion


namespace OMS.Ice.T4Generator.CodeBuilder
{
    internal class CSCodeBuilder : CodeBuilder
    {
        protected override string GetCodeTemplate()
        {
            return Resources.CSCodeTemplate;
        }

        protected override string GetIncludeTemplate()
        {
            return Resources.CSIncludeTemplate;
        }

        protected override StringBuilder CreateImports( IEnumerable<string> imports )
        {
            var result = new StringBuilder();

            foreach( var import in imports )
                result.AppendLine( string.Format( "using {0};", import ) );

            return result;
        }

        protected override StringBuilder CreateFields( IEnumerable<Parameter> parameters )
        {
            var result = new StringBuilder();

            foreach( var parameter in parameters )
                result.AppendLine( string.Format( "\t\tprivate {0} {1};", parameter.Type, parameter.Name ) );

            return result;
        }

        protected override StringBuilder CreateParameters( IEnumerable<Parameter> parameters )
        {
            var result = new StringBuilder();

            var first = true;
            foreach( var parameter in parameters )
            {
                if( !first )
                    result.Append( ", " );
                first = false;

                result.Append( string.Format( "{0} {1}", parameter.Type, parameter.Name ) );
            }

            return result;
        }

        protected override StringBuilder CreateCallParameters( IEnumerable<Parameter> parameters )
        {
            var result = new StringBuilder();

            var first = true;
            foreach( var parameter in parameters )
            {
                if( !first )
                    result.Append( ", " );
                first = false;

                result.Append( string.Format( "{0}", parameter.Name ) );
            }

            return result;
        }

        protected override StringBuilder CreateFieldInitializers( IEnumerable<Parameter> parameters )
        {
            var result = new StringBuilder();

            foreach( var parameter in parameters )
                result.AppendLine( string.Format( "\t\t\tthis.{0} = {0};", parameter.Name ) );

            return result;
        }

        protected override void CreateTextBlock( StringBuilder result, IEnumerable<LineInfo> content )
        {
            foreach( var line in content )
                result.AppendLine( string.Format( "\t\t\tWrite( \"{0}{1}\" );", Escape( line.Text ), line.HasEol ? GetEndOfLine() : string.Empty ) );
        }

        protected override void CreateInlineCode( StringBuilder result, string statement )
        {
            result.AppendLine( string.Format( "\t\t\tWrite( {0} );", statement ) );
        }

        protected override StringBuilder CreateMethodCall( StringBuilder result, IncludeDirective directive )
        {
            var parameters = GetParameters( IncludedTemplates[directive] );

            result.AppendLine( string.Format( "\t\t\t{0}TemplateMethod({1});", directive.Name, CreateCallParameters( parameters ) ) );

            return result;
        }

        protected override string BeginLinePragma( Part part )
        {
            return string.Format( "#line {0} \"{1}\"\r\n", part.Line, part.Source );
        }

        protected override string EndLinePragma()
        {
            return string.Empty;
        }


        private static string Escape( string text )
        {
            return text.Replace( "\\", "\\\\" ).Replace( "\"", "\\\"" );
        }

        protected override string GetEndOfLine()
        {
            switch( EndOfLine )
            {
                case EndOfLine.CR:
                    return @"\r";
                case EndOfLine.LFCR:
                    return @"\n\r";
                case EndOfLine.CRLF:
                    return @"\r\n";
                case EndOfLine.LF:
                    return @"\n";
                case EndOfLine.NEL:
                    return @"\u0085";
                case EndOfLine.LS:
                    return @"\u2028";
                case EndOfLine.PS:
                    return @"\u2029";
                default:
                    return @"\r\n";
            }
        }

        protected override string EscapeIdentifier( string possibleIdentifier )
        {
            return possibleIdentifier.StartsWith( "@" ) ? possibleIdentifier : "@" + possibleIdentifier;
        }
    }
}